/*
 * 人员管理菜单 - 人员管理菜单导航提供程序
 * 
 * 主要功能：
 * - 提供人员管理菜单
 * - 演示导航菜单的使用
 * - 支持权限控制
 * - 提供用户友好的导航
 */

using Lombiq.TrainingDemo.Controllers;
using Lombiq.TrainingDemo.Permissions;
using Microsoft.Extensions.Localization;
using OrchardCore.Mvc.Core.Utilities;
using OrchardCore.Navigation;
using System;
using System.Threading.Tasks;

namespace Lombiq.TrainingDemo.Navigation;

/// <summary>
/// 人员管理菜单 - 提供人员管理菜单导航
/// 
/// 主要用途：
/// - 提供人员管理菜单
 //* - 演示导航菜单的使用
 //* - 支持权限控制
 //* - 提供用户友好的导航
 //* 
 //* 使用场景：
/// - 在管理界面中显示人员管理菜单
/// - 提供人员管理的访问入口
/// - 支持权限控制的菜单显示
/// - 提供用户友好的导航体验
/// 
/// 设计原因：
/// - 为人员管理提供导航入口
/// - 实现权限控制的菜单显示
/// - 支持本地化的菜单文本
/// - 提供统一的导航体验
/// 
/// 设计模式：
/// - 菜单模式：实现INavigationProvider接口
/// - 权限模式：使用权限检查控制访问
/// - 本地化模式：使用IStringLocalizer支持多语言
/// - 构建模式：使用NavigationBuilder构建菜单
/// </summary>
// INavigationProvider用于构建不同类型的导航（不仅仅是管理菜单）。
// 不要忘记在服务提供程序中注册此类（请参阅：Startup.cs）。
public sealed class PersonsAdminMenu : INavigationProvider
{
    private readonly IStringLocalizer T;

    /// <summary>
    /// 构造函数 - 注入本地化服务
    /// </summary>
    /// <param name="stringLocalizer">字符串本地化器</param>
    public PersonsAdminMenu(IStringLocalizer<PersonsAdminMenu> stringLocalizer) => T = stringLocalizer;

    /// <summary>
    /// 构建导航 - 构建人员管理菜单
    /// 
    /// 功能说明：
    /// - 构建人员管理菜单结构
    /// - 添加菜单项和子菜单
    /// - 设置菜单权限控制
    /// - 提供本地化菜单文本
    /// 
    /// 菜单结构：
    /// - 人员页面主菜单
    /// - 测试子菜单
    /// - 人员列表子菜单（包含最新项目和最旧项目）
    /// - 权限控制设置
    /// 
    /// 使用场景：
    /// - 管理员访问人员管理功能
    /// - 查看人员列表
    /// - 管理人员权限
    /// - 提供用户友好的导航
    /// </summary>
    /// <param name="name">导航名称</param>
    /// <param name="builder">导航构建器</param>
    /// <returns>完成的任务</returns>
    public ValueTask BuildNavigationAsync(string name, NavigationBuilder builder)
    {
        // name参数区分不同的菜单类型。在我们的情况下是"admin"，所以让我们检查正在构建的菜单是否用于管理。
        if (!string.Equals(name, "admin", StringComparison.OrdinalIgnoreCase))
        {
            return ValueTask.CompletedTask;
        }

        // 构建器将在不同级别添加不同的菜单项。这里我们将创建一个3级菜单。
        // 第一级菜单是您进入仪表板时首先看到的内容，子菜单项是您点击此菜单时看到的内容。
        // 它应该有一个位置参数，这将是管理菜单中的位置。
        builder.Add(T["Person Pages"], "5", menu => menu
            // 第一级项目应该是一个好看的菜单项，所以让我们添加一个类名和ID。
            // 如果您想覆盖菜单项形状（因为这些也是形状）以便为其添加一个好看的图标，可以使用它。
            // 如果您想覆盖它，那么在创建cshtml文件时使用NavigationItemText-[id].Id替代。

            // 下一站：查看Views/NavigationItemText-persons.Id.cshtml中是如何完成的，然后回到这里！
            .AddClass("persons").Id("persons")
            // 这意味着顶级菜单项也将指向其第一个子项目指向的操作。
            // 现在这是常规做法，但是，它确实取决于管理主题。TheAdmin主题永远不会将其链接到第一个子项，
            // 它始终是一个没有链接的下拉菜单。
            .LinkToFirstChild(value: true)
            // 现在让我们添加子菜单项，使用与第一级项目相同的Add()方法，但链接到此项目。
            .Add(T["Test"], subitem => subitem
                // Action方法将菜单项绑定到操作。这是我们添加到AdminController的测试操作，
                // 以查看这是否自动工作。注意使用Orchard的ControllerName()辅助方法。
                .Action(
                    nameof(AdminController.Index),
                    typeof(AdminController).ControllerName(),
                    new { area = $"{nameof(Lombiq)}.{nameof(TrainingDemo)}" })
            )
            // 添加另一个菜单项，它将显示多个Person项目。但是，将此项目分支到两个不同的第三级项目！
            .Add(T["Person List"], subitem => subitem
                .LinkToFirstChild(value: true)

                .Add(T["Newest Items"], thirdLevelItem => thirdLevelItem
                    .Action(
                        nameof(AdminController.PersonListNewest),
                        typeof(AdminController).ControllerName(),
                        new { area = $"{nameof(Lombiq)}.{nameof(TrainingDemo)}" })
                    // 这意味着第一个子菜单项将指向我们的人员列表仪表板，并且只显示给拥有AccessPersonListDashboard权限的用户。
                    // 警告：这并不意味着其他人无法直接访问它：我们也必须在控制器中检查！
                    .Permission(PersonPermissions.AccessPersonListDashboard)
                    // 可选地将您的菜单项标记为显示在菜单外部的本地导航形状上。
                    // 最可能的情况是，如果主题不支持第三级菜单项，它将在其他地方显示它们。
                    // 在TheAdmin主题中，由于支持三级菜单，这不会产生任何差异。
                    .LocalNav())

                .Add(T["Oldest Items"], thirdLevelItem => thirdLevelItem
                    .Action(
                        nameof(AdminController.PersonListOldest),
                        typeof(AdminController).ControllerName(),
                        new { area = $"{nameof(Lombiq)}.{nameof(TrainingDemo)}" })
                    .Permission(PersonPermissions.AccessPersonListDashboard)
                    .LocalNav())));

        return ValueTask.CompletedTask;
    }
}

// 下一站：让我们回到Controllers/AdminController！
